/********************************************************************
*	Author: Andy Wu
*	Description: Source file to handle data from the data segments
*	Modifications:
*		-Created on 02/19/2011
*		-added outline of some functions, still a work in progress, still need to 
*			understand how access information in vectors... 02/22/2012
*		-accidentally deleted folder containing this file on 03/04/2012 using WinSCP
*			when trying to move files about and was unable to recover the file;
*			I have continued working from an older copy of the file from about 2
*			weeks back but much of code for getting data from vectors, etc. was lost
*			-03/05/2012
*		-basically started working from scratch again, added outline of functions to handle
*			printing values from test cases that have to be rewritten since the code was
*			lost; also add function to be used to convert data from data segment to binary
*			etc.; functions are mostly either inoperational or not tested; only operational
*			part is the function written to convert string into binary values (though there
*			are still a few bugs), will continue to work on these over the next few weeks
*			but will need a bit of a better understanding of what I'm doing first, will
*			need to know who I will need to pass to and what and how they want me to pass
*			to them before thinking what I will ultimately decide to do...-3/05/2012
*			
**********************************************************************/

#include <iostream>
using std::cerr;
using std::cout;
using std::cin;
using std::endl;

#include <cstdlib> // for exit function

#include "AssemblerClasses.h"
#include "dsegment.h"
#include <cstring>
#include <stdio.h>
#include <sstream>
#include <string>

/*function to test functions by printing out the generated machine code*/
void dsegprinttest(AssemblerData *a);

//main function to check functions
int main()
	{
	//AssemblerData a=AssemblerData::AssemblerData();



	/*testing conversion from string to binary*/
	string str,bin;
	cout<<"Enter string: ";
	getline(cin,str);
	bin=strtobinconv(str);
	cout<<bin<<endl;

//	(*a).mc_data= dsegmc(a);
	/*dsegprinttest(a);*/
	return 0;
	}

//dseg::dseg()	//constructor for dseg class
//	{
//	
//	}


void directives(vector<AssemblyCommands> dir)
	{
//	char c[];
//	int n[];
//	double d[];
//	float f[];
	
//	sscanf();
//	switch dir
		{
//		case ".align":
			
		}

/*	the directives I will need to handle and their description:
	.align n	 	Align the next datum on a 2n byte boundary.
				For example, .align 2 aligns the next value on a word boundary. .align 0 turns off automatic alignment of .half, .word, .float, and .double directives until the next .data or .kdata directive.
	.ascii str 		Store the string in memory, but do not null-terminate it.
	.asciiz str	 	Store the string in memory and null-terminate it.
	.byte b1,..., bn 	Store the n values in successive bytes of memory.
	.data <addr> 		The following data items should be stored in the data segment. If the optional argument addr is present, the items are stored beginning at address addr.
	.double d1,..., dn 	Store the n floating point double precision numbers in successive memory locations.
	.extern sym size 	Declare that the datum stored at sym is size bytes large and is a global symbol. This directive enables the assembler to store the datum in a portion of the data segment that is efficiently accessed via register $gp.
	.float f1,..., fn 	Store the n floating point single precision numbers in successive memory locations.
	.globl sym		Declare that symbol sym is global and can be referenced from other files.
	.half h1,..., hn 	Store the n 16-bit quantities in successive memory halfwords.
	.kdata <addr> 	The following data items should be stored in the kernel data segment. If the optional argument addr is present, the items are stored beginning at address addr.
	.ktext <addr> 	The next items are put in the kernel text segment. In SPIM, these items may only be instructions or words (see the .word directive below). If the optional argument addr is present, the items are stored beginning at address addr.
	.space n 		Allocate n bytes of space in the current segment (which must be the data segment in SPIM).
	.text <addr> 		The next items are put in the user text segment. In SPIM, these items may only be instructions or words (see the .word directive below). If the optional argument addr is present, the items are stored beginning at address addr.
	.word w1,..., wn 	Store the n 32-bit quantities in successive memory words. SPIM does not distinguish various parts of the data segment (.data, .rdata and .sdata).
*/
	}


/*function to access tokenized data in the vector and return the data*/
/*work in progress*/
string getdseg(AssemblerData a)
	{
	//format of syntax: (*a)[235].fadgdsag()
	
//	vector<AssemblyCommands> *dir=a.ret_dir();
	string str;
	
//	for (int i=0; i < dir.size(); i++) /*for loop to scan through the vector*/
		{
		
		/*access directive vector in class AssemblerData and
		 try to look for portion regarding data segment*/
//		if((strcmp(dir.ret_gen(),".data"))||strcmp(dir.ret_gen(),".kdata"))
			{
//			vector<AssemblyCommands> *dir=a.ret_dir();
//			unsigned int ln=dir.ret_ln();
//			if((ln+1)==)	/*trying to retrieve data from vector by looking for information from the nextline of the file*/
				{
					
				}
			}
		}
	return str;
	}

/*takes data from AssemblerData class and converts data to binary and store it in a vector*/
vector<unsigned int> dsegmc(AssemblerData a)
	{
	//getdseg(a);/*get tokenized data*/
	
	vector <unsigned int> veci;
	return veci;
	}

/*function to test functions by printing out the generated machine code and other related values*/
void dsegprinttest(AssemblerData *a)
	{
	
	
	}

/*takes string and returns its binary equivalent as type string*/
/*still needs a bit of work*/
string strtobinconv(string str)
	{
	char letter;
	int ascii, len, binary[8], total;
	stringstream ss;

	len = strlen(str.c_str());  /* get the number of characters in str. */
	/* this loop is executed for each letter in the string. */
	for(int i = 0; i<len; i++)
		{
		total = 0;
		letter = str[i]; /* store the first letter */
		ascii = letter;    /* put that letter into an int, so we can see its ASCII number */
		
		//the space and comma are among many characters that do not include the extra zero causing output to be wrong
		if ((ascii!=32)&&(ascii!=36)&&(ascii!=44)&&(ascii!=45)&&(ascii!=46)&&(ascii!=48)
			&&(ascii!=49)&&(ascii!=50)&&(ascii!=51)&&(ascii!=52)&&(ascii!=53)
			&&(ascii!=54)&&(ascii!=55)&&(ascii!=56)&&(ascii!=57)&&(ascii!=58))
			{
			while(ascii>0) /* This while loop converts the ASCII # into binary,
       	                 stores it backwards into the binary array. */
				{
				if((ascii%2)==0)
					{
					binary[total] = 0;
					ascii = ascii/2;
					total++; /* counting number of numbers in the array. */
					}
				else
					{
					binary[total] = 1;
					ascii = ascii/2;
					total++;
					}
				}

			/* this while loop displays the binary code for that letter. */
			binary[total]=0;
			while(total>=0)
				{
				//cout<<binary[total]<<endl;
				ss<<binary[total];
				total--;
				}
			}
		else 
			{
			switch(ascii)
				{
				case 32:	//space
					ss<<"00100000";
					break;
				case 36:	//dollar symbol
					ss<<"00100100";
					break;
				case 44:	//comma
					ss<<"00101100";
					break;
				case 45:	//minus
					ss<<"00101101";
					break;
				case 46:	//period
					ss<<"00101110";
					break;
				case 48:	//0
					ss<<"00110000";
					break;
				case 49:	//1
					ss<<"00110001";
					break;
				case 50:	//2
					ss<<"00110010";
					break;
				case 51:	//3
					ss<<"00110011";
					break;
				case 52:	//4
					ss<<"00110100";//period
					break;
				case 53:	//5
					ss<<"00110101";//period
					break;
				case 54:	//6
					ss<<"00110110";//period
					break;
				case 55:	//7
					ss<<"00110111";//period
					break;
				case 56:	//8
					ss<<"00111000";//period
					break;
				case 57:	//9
					ss<<"00111001";//period
					break;
				case 58:	//colon
					ss<<"00111010";
					break;
				}
			}
		}
	return ss.str();
	}
